package br.ufrn.sipac.patrimonio.coletor.activity;

import java.io.IOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.ExecutionException;

import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import br.ufrn.sipac.patrimonio.auxiliares.ConstantesOperacoes;
import br.ufrn.sipac.patrimonio.auxiliares.StatusLevantamento;
import br.ufrn.sipac.patrimonio.auxiliares.TipoStatusBem;
import br.ufrn.sipac.patrimonio.coletor.R;
import br.ufrn.sipac.patrimonio.coletor.controller.DatabaseController;
import br.ufrn.sipac.patrimonio.coletor.controller.LevantamentoController;
import br.ufrn.sipac.patrimonio.coletor.controller.MainController;
import br.ufrn.sipac.patrimonio.coletor.dominio.Bem;
import br.ufrn.sipac.patrimonio.coletor.dominio.ItemLevantamento;
import br.ufrn.sipac.patrimonio.coletor.dominio.Localidade;
import br.ufrn.sipac.patrimonio.coletor.dominio.Persistencia;
import br.ufrn.sipac.patrimonio.coletor.dominio.Unidade;
import br.ufrn.sipac.patrimonio.coletor.dominio.UsuarioColetor;
import br.ufrn.sipac.patrimonio.coletor.exception.DatabaseException;
import br.ufrn.sipac.patrimonio.coletor.exception.NegocioException;
import br.ufrn.sipac.patrimonio.coletor.exception.TransmissaoException;
import br.ufrn.sipac.patrimonio.coletor.transmissao.GenericSOAP;

/**
 * Activity responsável por ler os bens e salvar os dados do levantamento.
 * 
 * @author Giuliana Silva Bezerra import java.util.Iterator; import
 *         java.util.List; import java.util.Vector; import
 *         java.util.concurrent.ExecutionException;
 */
public class LeituraActivity extends Activity {
	/** Permite visualizar os detalhes do levantamento atual. */
	private Button detalhes;
	/** Permite finalizar o levantamento enviando os dados para o SIPAC. */
	private Button finalizar;
	/** Permite incluir o bem como um item do levantamento. */
	private Button incluir;
	/**
	 * Opção que permite utilizar o leitor de código de barras para recuperar o
	 * tombo do bem.
	 */
	private CheckBox leitorCodigoBarras;
	/** Contém a informação da Unidade/Localidade do levantamento. */
	private TextView unidadeLocalidade;
	/** Permite escolher o tombo associado ao bem. */
	private EditText tombo;
	/**
	 * Contém o nome do bem associado ao tombo, caso ele esteja cadastrado no
	 * sistema.
	 */
	private TextView nomeBem;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_leitura);

		// Mapear os componente da tela
		detalhes = (Button) findViewById(R.id.button2);
		finalizar = (Button) findViewById(R.id.button1);
		incluir = (Button) findViewById(R.id.Button01);
		leitorCodigoBarras = (CheckBox) findViewById(R.id.checkBox1);
		unidadeLocalidade = (TextView) findViewById(R.id.textView3);
		tombo = (EditText) findViewById(R.id.editText1);
		nomeBem = (TextView) findViewById(R.id.textView6);

		// Inicializa os componentes
		nomeBem.setText("");

		// Adiciona listeners
		detalhes.setOnClickListener(new VerDetalhesColetaListener());
		incluir.setOnClickListener(new SubmeteDadosListener());
		finalizar.setOnClickListener(new FinalizarLevantamentoListener());
		leitorCodigoBarras
				.setOnCheckedChangeListener(new IniciarLeitorCodigoBarrasListener());
		tombo.addTextChangedListener(new TextWatcher() {
			public void afterTextChanged(Editable s) {
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				try {
					verificaTombo();
				} catch (Exception e) {
				}
			}
		});
		tombo.requestFocus();
		// Verifica se o modo de operação é offline
		if (MainController.getTipoAutenticacao() == ConstantesOperacoes.MODO_OFFLINE) {
			final AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle("INFO");
			builder.setMessage("Alguns bens não estão sincronizados com o SIPAC. Durante a finalização do levantamento esse bens serão sincronizados.");
			builder.setPositiveButton("OK", new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
				}
			});
			builder.show();
		}
	}

	/**
	 * Processa o número de tombo fornecido pelo usuário para recuperar os dados
	 * do bem levantado.
	 * 
	 * @throws XmlPullParserException
	 * @throws IOException
	 * @throws NumberFormatException
	 * @throws ConnectException
	 * @throws ExecutionException
	 * @throws InterruptedException
	 */
	private void verificaTombo() throws DatabaseException, TransmissaoException {
		if (tombo.getText().length() == 10) {
			GenericSOAP soap = new GenericSOAP();
			try {
				Bem bem = null;

				// Verifica o modo de operação
				if (MainController.getTipoAutenticacao() == ConstantesOperacoes.MODO_ONLINE)
					bem = soap.findByNumCod(
							Integer.parseInt(tombo.getText().toString()), this);
				else
					bem = (Bem) DatabaseController.findBemByTombo(this,
							Integer.parseInt(tombo.getText().toString()))
							.get(0);

				if (bem != null) {
					LevantamentoController.getInstance().setBem(bem);
					nomeBem.setText(bem.getDenominacao());
					Persistencia unidade = DatabaseController.findUnidadeById(
							this, bem.getUnidade().getId());
					if (unidade == null) {
						unidade = null;
						unidadeLocalidade.setText(" Desconhecida");
					} else {
						unidadeLocalidade.setText(" "
								+ ((Unidade) unidade).getSigla());
						if (bem.getLocal().getId() > 0) {
							Persistencia localidade = DatabaseController
									.findLocalidadeById(this, bem.getLocal()
											.getId());
							unidadeLocalidade.setText(" "
									+ ((Unidade) unidade).getSigla() + " / "
									+ ((Localidade) localidade).getCodigo());
						} else
							unidadeLocalidade.setText(" "
									+ ((Unidade) unidade).getSigla() + " / "
									+ "Sem Localidade");
					}
					incluir.requestFocus();
				} else {
					nomeBem.setText("");
					unidadeLocalidade.setText("");
					LevantamentoController.getInstance().setBem(new Bem());
				}
			} catch (DatabaseException e) {
			} catch (TransmissaoException e) {
			}
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.leitura, menu);
		return true;
	}

	/**
	 * Carrega menu da aplicação.
	 */
	private void iniciaMenu() {
		finish();
		Intent intent = new Intent(this, MenuActivity.class);
		startActivity(intent);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.item2:
			iniciaMenu();
		case R.id.item1:
			finish();
		}
		return false;
	}

	public void visualizarDetalhesColeta() {
		finish();
		Intent intent = new Intent(this, DetalhesColetaActivity.class);
		startActivity(intent);
	}

	/**
	 * Método que realiza a finalização de um levantamento.
	 * 
	 * @throws NegocioException
	 * 
	 * @throws DatabaseException
	 */
	public void finalizaLevantamento() throws NegocioException {
		Collection<Persistencia> bens = new ArrayList<Persistencia>();
		Vector vec = new Vector();
		try {
			// Verifica se há itens no levantamento
			if (MainController.getBensBaixados().size() == 0
					&& MainController.getBensNaoCadastrados().size() == 0
					&& MainController.getBensInventariados().size() == 0
					&& MainController.getBensNaoInventariados().size() == 0)
				throw new NegocioException(
						"Não há itens inseridos no levantamento!", this);
			else {
				bens.addAll(MainController.getBensBaixados());
				bens.addAll(MainController.getBensNaoCadastrados());
				bens.addAll(MainController.getBensInventariados());
				bens.addAll(MainController.getBensNaoInventariados());

				Iterator it = bens.iterator();
				while (it.hasNext()) {
					ItemLevantamento item = (ItemLevantamento) it.next();
					// Evitar erro no servidor
					if (item.getMarca() == null)
						item.setMarca("Não informada");
					vec.addElement(item.toString());
				}

				if (LevantamentoController.getInstance().getLevantamento().getUsuario() != null
						&& LevantamentoController.getInstance().getLevantamento().getUsuario()
								.getId() > 0) {
					GenericSOAP soap = new GenericSOAP();
					Persistencia obj = DatabaseController.findUsuarioById(this,
							LevantamentoController.getInstance().getLevantamento().getUsuario()
									.getId());
					UsuarioColetor usuario = (UsuarioColetor) obj;
					obj = DatabaseController
							.findLocalidadeById(this, 
									LevantamentoController.getInstance().getLevantamento().getLocal().getId());
					Localidade localidade = (Localidade) obj;
					// Verifica as permissões do usuário na unidade do
					// levantamento.
					if (usuario.getUnidade() != null
							&& usuario.getUnidade().getId() > 0) {
						Collection unidades = soap.findUnidadesPermissao(
								usuario.getLogin(), this);
						boolean semPermissao = true;
						if (unidades != null && unidades.size() > 0) {
							for (Object uni : unidades) {
								if (((Unidade) uni).getId() == localidade
										.getUnidade().getId()) {
									semPermissao = false;
									break;
								}
							}
						}

						if (semPermissao) {
							throw new NegocioException(
									"O usuário não possui permissão para efetuar o levantamento nessa unidade.",
									this);
						}
					}

					Boolean sucess = Boolean
							.parseBoolean(soap.gravarLevantamento(
									LevantamentoController.getInstance().getLevantamento(), vec, this));
					if (sucess) {
						// Atualiza levantamento para finalizado
						LevantamentoController.getInstance().getLevantamento().setStatus(
								StatusLevantamento.FINALIZADO);
						DatabaseController.updateLevantamento(
								LevantamentoController.getInstance().getLevantamento(), this);

						final AlertDialog.Builder builder = new AlertDialog.Builder(
								this);
						builder.setTitle("Aviso");
						builder.setMessage("Levantamento finalizado com sucesso!");
						builder.setPositiveButton("OK", new OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								iniciaMenu();
							}
						});
						builder.show();
					} else {
						throw new TransmissaoException(this);
					}
				} else {
					LevantamentoController.getInstance().setItens(bens);
					iniciaAutenticacaoFinalizar();
				}
			}
		} catch (DatabaseException e) {
		} catch (TransmissaoException e) {
		}
	}

	/**
	 * Encaminha para a tela de autenticação no sipac.
	 */
	private void iniciaAutenticacaoFinalizar() {
		finish();
		Intent intent = new Intent(this, AutenticarFinalizarActivity.class);
		startActivity(intent);
	}

	/**
	 * Inicia a aplicação de leitura de código de barras caso o usuário
	 * selecione esse modo de leitura.
	 */
	public void iniciaLeitorCodigoBarras(boolean isChecked) {
		if (isChecked) {
			// Chama o leitor de código de barras
			Intent intent = new Intent("com.google.zxing.client.android.SCAN");
			startActivityForResult(intent, 0);
		}

	}

	/**
	 * Efetua a leitura do código de barras utilizando o aplicativo de leitura e
	 * exibe o tombo associado ao material.
	 */
	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
		if (requestCode == 0) {
			if (resultCode == Activity.RESULT_OK) {
				String contents = intent.getStringExtra("SCAN_RESULT");
				String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
				Toast.makeText(this, contents + " " + format, Toast.LENGTH_LONG)
						.show();
				tombo.setText(contents);
				try {
					verificaTombo();
				} catch (DatabaseException e) {
				} catch (TransmissaoException e) {
				}
			} else if (resultCode == Activity.RESULT_CANCELED) {
				// Usuário não fez a leitura do código de barras
			}
		}
	}

	/**
	 * Chama a activity responsável por incluir um bem no levantamento
	 * patrimonial.
	 * 
	 * @throws NegocioException
	 */
	public void incluiBem() throws NegocioException {
		Intent intent = new Intent(this, CadastroItemLevantamentoActivity.class);
		// Nenhum dado informado
		if (tombo.getText() == null)
			throw new NegocioException("Informe um número de tombo válido.",
					this);

		// Tombo informado não possui 10 caracteres
		if (tombo.getText().toString().trim().length() != 10)
			throw new NegocioException(
					"O tombo deve possuir 10 caracteres numéricos.", this);

		Bem bem = LevantamentoController.getInstance().getBem();
		if (bem != null && bem.getId() != 0) {
			ItemLevantamento item = new ItemLevantamento();
			item.setBem(bem);
			item.setMarca(null);
			item.setLevantamento(LevantamentoController.getInstance().getLevantamento());
			item.setEstado(bem.getStatus());
			item.setNumTombamento(String.valueOf(bem.getNumTombamento()));
			item.setDenominacao(bem.getDenominacao());

			try {
				// DatabaseController
				// .capturarMaiorId(ItemLevantamento.class, this);
				DatabaseController.create(item, this);
				Persistencia unidade = DatabaseController.findUnidadeById(this,
						bem.getUnidade().getId());
				if (unidade == null) {
					// O item já foi adicionado ao levantamento
					if (MainController.getBensNaoInventariados().contains(item))
						throw new NegocioException("Tombo já adicionado.", this);

					MainController.getBensNaoInventariados().add(item);
					MainController.setCountBensNaoInventariados(MainController
							.getCountBensNaoInventariados() + 1);
				}
				// Bens alienadositem.setDenominacao(bem.getDenominacao());

				if (bem.getStatus() == TipoStatusBem.ALIENADO) {
					if (MainController.getBensNaoInventariados().contains(item))
						throw new NegocioException("Tombo já adicionado.", this);

					MainController.setCountBensBaixados(MainController
							.getCountBensBaixados() + 1);
					MainController.getBensBaixados().add(item);
				} else {
					if (unidade != null) {
						if (MainController.getBensInventariados()
								.contains(item))
							throw new NegocioException("Tombo já adicionado.",
									this);

						MainController.setCountBensInventariados(MainController
								.getCountBensInventariados() + 1);
						MainController.getBensInventariados().add(item);
					}
				}
			} catch (DatabaseException e) {
			}
			tombo.setText("");
			tombo.requestFocus();
			nomeBem.setText("");
			unidadeLocalidade.setText("");
			incluir.requestFocus();
			LevantamentoController.getInstance().setBem(null);
			return;
		}
		MainController.setTombo(tombo.getText().toString());
		finish();
		startActivity(intent);
	}

	/**
	 * Listener que permite visualizar os detalhes da coleta.
	 */
	public class VerDetalhesColetaListener implements Button.OnClickListener {
		@Override
		public void onClick(View arg0) {
			visualizarDetalhesColeta();
		}
	}

	/**
	 * Listener que lida com a submissão dos dados de um bem.
	 */
	public class SubmeteDadosListener implements Button.OnClickListener {
		@Override
		public void onClick(View arg0) {
			try {
				incluiBem();
			} catch (NegocioException e) {
			}
		}
	}

	/**
	 * Listener que lida com a submissão dos dados do levantamento no sipac.
	 */
	public class FinalizarLevantamentoListener implements
			Button.OnClickListener {
		@Override
		public void onClick(View arg0) {
			try {
				finalizaLevantamento();
			} catch (NegocioException e) {
			}
		}
	}

	/**
	 * Listener que inicia a aplicação de leitura de código de barras.
	 */
	public class IniciarLeitorCodigoBarrasListener implements
			OnCheckedChangeListener {
		@Override
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			iniciaLeitorCodigoBarras(isChecked);
		}
	}

	@Override
	public void onBackPressed() {
		// Desabilita botão voltar.
	}
}
